import axios, { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios'
import qs from 'qs'
import { cleanSession, getToken, setToken } from '@/utils/auth'
import { getUrlParams } from '@/utils/filters'
import { alertMsg } from '@/utils/utils'

export interface Result<T = any> {
    code: number
    msg: string
    data: T
}
export enum StatusCode {
    NoAuth = 401, //token失效
    Success = 200 //返回成功
}
class request {
    private instance: AxiosInstance
    public baseUrl: string | undefined
    // 构造函数 给instance进行初始化
    constructor(config: AxiosRequestConfig) {
        this.baseUrl = config.baseURL
        // 创建axios实例
        this.instance = axios.create(config)
        // 拦截器配置
        this.interceptors()
    }
    // 拦截器
    private interceptors() {
        // 请求拦截
        this.instance.interceptors.request.use(
            (config: AxiosRequestConfig) => {
                let token = getToken()
                if (token) {
                    //把token添加到请求头部
                    config.headers = {
                        ...config.headers,
                        Authorization: 'Bearer ' + token
                    }
                }
                return config
            },
            (error: any) => {
                // 错误抛到业务代码
                error.data = {}
                error.data.msg = '服务器异常，请联系管理员！'
                return error
            }
        )
        // 响应拦截
        this.instance.interceptors.response.use(
            (res: AxiosResponse) => {
                if (res && res.data) {
                    const data = res.data as any
                    if (data.code == StatusCode.NoAuth) {
                        // 清空sessionStorage数据
                        // cleanSession()
                        // 跳到登录
                        // window.location.href = '/login?' + getUrlParams()
                        // return res;
                    } else if (data.code == StatusCode.Success) {
                        // 这里我们在服务端将正确返回的状态码标为200
                        return res
                    } else {
                        alertMsg(data.msg || '服务器出错!')
                        return false // 返回false
                    }
                } else {
                    alertMsg('服务器无法访问!')
                }
            },
            (error: any) => {
                // 这里是遇到报错的回调
                console.log('进入错误', error.response)
                error.data = {}
                if (error && error.response) {
                    switch (error.response.status) {
                        case 400:
                            error.data.msg = '错误请求'
                            console.log(error.data.msg)
                            break
                        case 401:
                            error.data.msg = '未授权，请重新登录'
                            console.log(error.data.msg)
                            break
                        case 403:
                            error.data.msg = '拒绝访问'
                            console.log(error.data.msg)
                            break
                        case 404:
                            error.data.msg = '请求错误,未找到该资源'
                            console.log(error.data.msg)
                            break
                        case 405:
                            error.data.msg = '请求方法未允许'
                            console.log(error.data.msg)
                            break
                        case 408:
                            error.data.msg = '请求超时'
                            console.log(error.data.msg)
                            break
                        case 500:
                            error.data.msg = '服务器端出错'
                            console.log(error.data.msg)
                            break
                        case 501:
                            error.data.msg = '网络未实现'
                            console.log(error.data.msg)
                            break
                        case 502:
                            error.data.msg = '网络错误'
                            console.log(error.data.msg)
                            break
                        case 503:
                            error.data.msg = '服务不可用'
                            console.log(error.data.msg)
                            break
                        case 504:
                            error.data.msg = '网络超时'
                            console.log(error.data.msg)
                            break
                        case 505:
                            error.data.msg = 'http版本不支持该请求'
                            console.log(error.data.msg)
                            break
                        default:
                            error.data.msg = `连接错误${error.response.status}`
                            console.log(error.data.msg)
                            cleanSession()
                    }
                } else {
                    error.data.msg = '连接到服务器失败'
                    console.log(error.data.msg)
                }
                // return Promise.reject(error)
                return error
            }
        )
    }

    getParms(parms: any): string {
        let _params = ''
        if (Object.is(parms, undefined || null)) {
            _params = ''
        } else {
            for (const key in parms) {
                if (parms.hasOwnProperty(key)) {
                    _params += `${parms[key]}/`
                }
            }
        }
        //去掉参数最后一位/
        if (_params) _params = _params.substr(0, _params.length - 1)
        return _params
    }

    /**
     *  http://localhost:8089/api/user/getUserById?userId=10
     * @param url   /api/user/getUserById
     * @param parms  {userId:10}
     * @returns
     */
    get<T = any>(url: string, parms?: any): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance
                .get<T>(url, {
                    params: parms,
                    paramsSerializer: (parms) => {
                        return qs.stringify(parms)
                    }
                })
                .then((res) => {
                    resolve(res.data as any)
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }

    /**
     *  http://localhost:8089/api/user/10/test
     * @param url   /api/user/getUserById
     * @param parms  {userId:10, username: 'test'}
     * @returns
     */
    getRestApi<T = any>(url: string, parms?: any): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance
                .get<T>(
                    this.getParms(parms)
                        ? `${url}/${this.getParms(parms)}`
                        : url
                )
                .then((res) => {
                    resolve(res.data as any)
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }

    // post请求
    post<T = any>(url: string, parms: any): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance
                .post<T>(url, parms, {
                    transformRequest: [
                        (params) => {
                            return JSON.stringify(params)
                        }
                    ],
                    headers: {
                        'Content-Type': 'application/json'
                    }
                })
                .then((res) => {
                    if (res) {
                        resolve(res.data as any)
                    } else {
                        return false
                    }
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }

    // 上传文件
    postFile<T = any>(url: string, formData: FormData): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance
                .post<T>(url, formData, {
                    headers: {
                        'Content-Type': 'multipart/form-data'
                    }
                })
                .then((res) => {
                    if (res) {
                        resolve(res.data as any)
                    } else {
                        return false
                    }
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }

    // put请求
    put<T = any>(url: string, parms: any): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance
                .put<T>(url + '/' + parms.id, parms, {
                    transformRequest: [
                        (params) => {
                            return JSON.stringify(params)
                        }
                    ],
                    headers: {
                        'Content-Type': 'application/json'
                    }
                })
                .then((res) => {
                    resolve(res.data as any)
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }

    /**
     * delete请求
     *  http://localhost:8089/api/user/10
     * @param url   /api/user
     * @param parms  {userId:10}
     * @returns
     */
    delete<T = any>(url: string, parms: any): Promise<Result<T>> {
        return new Promise((resolve, reject) => {
            this.instance
                .delete<T>(
                    this.getParms(parms)
                        ? `${url}/${this.getParms(parms)}`
                        : url
                )
                .then((res) => {
                    resolve(res.data as any)
                })
                .catch((error) => {
                    reject(error)
                })
        })
    }
}
export default request
